package org.example;

/*
 *  示例：[a, b=c, [d, e]]
 *
 *  语法:
 *  grammar NestedNameList;
 *  list     : '[' elements ']' ;
 *  elements : element (',' element)* ;
 *  element  : NAME '=' NAME
 *           | NAME
 *           | list
 *           ;
 *
 *  NAME     : ('a'..'z' | 'A'..'Z')+ ;   // NAME含有至少一个字母
 * */

public class ListLexer extends Lexer {

    public static final int NAME = 2; // ('a'..'z' | 'A'..'Z')+
    public static final int COMMA = 3; // ','
    public static final int LBRACK = 4; // '['
    public static final int RBRACK = 5; // ']'
    public static final int EQUAL = 6; // '='

    public static final String[] tokenNames = new String[]{
            "n/a",
            "<EOF>",
            "NAME",
            "COMMA",
            "LBRACK",
            "RBRACK",
            "EQUAL"
    };

    public ListLexer(String input) {
        super(input);
    }

    @Override
    public String getTokenName(int type) {
        return tokenNames[type];
    }

    // 判断当前字符是否为英文字母
    public boolean isLETTER() {
        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    }

    @Override
    public Token nextToken() {
        while (c != EOF) {
            switch (c) {
                case ' ':
                case '\t':
                case '\n':
                case '\r':
                    WS();
                    continue;
                case '[':
                    consume();
                    return BuildToken(LBRACK, "[");
                case ']':
                    consume();
                    return BuildToken(RBRACK, "]");
                case ',':
                    consume();
                    return BuildToken(COMMA, ",");
                case '=':
                    consume();
                    return BuildToken(EQUAL, "=");
                default:
                    if (isLETTER()) return NAME();
                    else throw new Error("非法字符：" + c);
            }
        }

        return BuildToken(EOF_TYPE, "<EOF>");
    }

    private Token BuildToken(int type, String text)
    {
        return new Token(type, getTokenName(type), text);
    }

    /**
     * NAME : ('a'..'z'|'A'..'Z')+; // NAME is sequence of >=1 letter
     */
    private Token NAME() {
        StringBuilder buf = new StringBuilder();
        do {
            buf.append(c);
            consume();
        } while (isLETTER());
        return BuildToken(NAME, buf.toString());
    }

    /**
     * WS : (' '|'\t'|'\n'|'\r')* ; // ignore any whitespace
     */
    void WS() {
        while (c == ' ' || c == '\t' || c == '\n' || c == '\r') consume();
    }
}
